package com.facebook.app.server.clustering;

import java.util.LinkedList;
import java.util.List;

import com.facebook.app.shared.clustering.Cluster;
import com.facebook.app.shared.clustering.Clusterable;

public class SimpleClustering implements ClusteringStrategy {

	private final int numberOfLoopsPerRequest;
	private final ClusterSimilarityStrategy similarityStrategy;

	private List<Clusterable> clusterElements;

	public SimpleClustering(ClusterSimilarityStrategy similarityStrategy, List<Clusterable> clusterElements) {
		
		this.similarityStrategy = similarityStrategy;

		if (clusterElements instanceof LinkedList) {
			this.clusterElements = clusterElements;
		} else {
			this.clusterElements = new LinkedList<Clusterable>(
					clusterElements);
		}

		// The number of loops per request should depend on
		// the number of elements in the Clusterable list.

		// for testing
		numberOfLoopsPerRequest = Integer.MAX_VALUE;
	}

	@Override
	public List<Clusterable> createClusters() {
		System.out.println("Info: Creating cluster");
		System.out.println("number of friends: " + clusterElements.size());
		double currentSimilarityScore;
		double maxSimilarityScore;

		Clusterable highestScoredPairFirstElement = null;
		Clusterable highestScoredPairSecondElement = null;

		for (int k = 0; k < numberOfLoopsPerRequest
				&& clusterElements.size() > 1; k++) {
			// this is *completely* unoptimized!
			maxSimilarityScore = Double.NEGATIVE_INFINITY;
			
			for (Clusterable outerElement : clusterElements) {
				for (Clusterable innerElement : clusterElements) {
					if (!outerElement.equals(innerElement)) {

						currentSimilarityScore = similarityStrategy.computeSimilarity(
								outerElement, innerElement);

						if (currentSimilarityScore > maxSimilarityScore) {
							highestScoredPairFirstElement = outerElement;
							highestScoredPairSecondElement = innerElement;
							maxSimilarityScore = currentSimilarityScore;
						}
					}
				}
			}

			clusterElements.remove(highestScoredPairFirstElement);
			clusterElements.remove(highestScoredPairSecondElement);
			
			Clusterable newNode = new Cluster(highestScoredPairFirstElement,
					highestScoredPairSecondElement, maxSimilarityScore);
			clusterElements.add(newNode);
		}
		System.out.println("Info: Finish");
		return clusterElements;
	}

}
